/**
 * This file is part of 1genia trampoline
 * Copyright (C) 2007 1genia (contact@1genia.com)
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; version 3 of the License. 
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; see the file COPYING.TXT.  If not,
 * write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301, USA. 
 **/
package com.genia.toolbox.persistence.memory.manager;

import java.util.Collection;

import com.genia.toolbox.persistence.basis.manager.AbstractRestrictionsManager;
import com.genia.toolbox.persistence.criteria.Criteria;
import com.genia.toolbox.persistence.criteria.criterion.Criterion;
import com.genia.toolbox.persistence.criteria.enumeration.MatchMode;
import com.genia.toolbox.persistence.criteria.field.Field;
import com.genia.toolbox.persistence.memory.criteria.MemoryCriteria;
import com.genia.toolbox.persistence.memory.criteria.criterion.MemoryAndJunction;
import com.genia.toolbox.persistence.memory.criteria.criterion.MemoryCriterion;
import com.genia.toolbox.persistence.memory.criteria.criterion.MemoryDualJunction;
import com.genia.toolbox.persistence.memory.criteria.criterion.MemoryFieldComparator;
import com.genia.toolbox.persistence.memory.criteria.criterion.MemoryFuzzyFieldComparator;
import com.genia.toolbox.persistence.memory.criteria.criterion.MemoryIsInCriterion;
import com.genia.toolbox.persistence.memory.criteria.criterion.MemoryIsNullCriterion;
import com.genia.toolbox.persistence.memory.criteria.criterion.MemoryJunction;
import com.genia.toolbox.persistence.memory.criteria.criterion.MemoryNotCriterion;
import com.genia.toolbox.persistence.memory.criteria.field.AbstractMemoryField;

/**
 * Memory implementation of the generic <code>RestrictionsManager</code> that
 * allows user to generate restriction to use with criteria.
 */
public class MemoryRestrictionsManager
    extends AbstractRestrictionsManager
{

  /**
   * Return a criterion that represents a conjunction.
   * 
   * @return a criterion that represents a conjunction
   */
  public MemoryJunction conjunction()
  {
    return new MemoryAndJunction(getMemoryPersistenceManager());
  }



  /**
   * Return a criterion that represents a disjunction.
   * 
   * @return a criterion that represents a disjunction
   */
  public MemoryJunction disjunction()
  {
    return new MemoryDualJunction(getMemoryPersistenceManager(), conjunction());
  }



  /**
   * Return a criterion that represents the equality between two fields.
   * 
   * @param field1
   *          the first field in the equality
   * @param field2
   *          the second field in the equality
   * @return a criterion representing <code>field1 == field2</code>
   */
  public Criterion equals(final Field field1, final Field field2)
  {
    return new MemoryFieldComparator(MemoryFieldComparator.FieldComparator.EQUALITY, ((AbstractMemoryField) field1), ((AbstractMemoryField) field2));
  }



  /**
   * getter for the persistenceManager property.
   * 
   * @return the persistenceManager
   */
  public MemoryPersistenceManager getMemoryPersistenceManager()
  {
    return (MemoryPersistenceManager) super.getPersistenceManager();
  }



  /**
   * Return a criterion that represents that a field is greater or equals to
   * another.
   * 
   * @param field1
   *          the first field in the comparaison
   * @param field2
   *          the second field in the comparaison
   * @return a criterion representing <code>field1 >= field2</code>
   */
  public Criterion greaterOrEquals(final Field field1, final Field field2)
  {
    return new MemoryFieldComparator(MemoryFieldComparator.FieldComparator.GREATER_OR_EQUALS, ((AbstractMemoryField) field1), ((AbstractMemoryField) field2));
  }



  /**
   * Return a criterion that represents that a field is greater than another.
   * 
   * @param field1
   *          the first field in the comparaison
   * @param field2
   *          the second field in the comparaison
   * @return a criterion representing <code>field1 > field2</code>
   */
  public Criterion greaterThan(final Field field1, final Field field2)
  {
    return new MemoryFieldComparator(MemoryFieldComparator.FieldComparator.GREATER_THAN, ((AbstractMemoryField) field1), ((AbstractMemoryField) field2));
  }



  /**
   * Return a criterion that represents that a field is contained in a
   * collection of objects.
   * 
   * @param field
   *          the field to search
   * @param collection
   *          the collection the field must be in
   * @return a criterion representing that <code>field</code> is contained in
   *         <code>collection</code>
   */
  public Criterion isIn(final Field field, final Collection<?> collection)
  {
    return new MemoryIsInCriterion(((AbstractMemoryField) field), collection);
  }



  /**
   * Return a criterion that represents that a field is contained is the main
   * result of another query.
   * 
   * @param field
   *          the field to search
   * @param criteria
   *          the second query
   * @return a criterion representing that <code>field</code> is contained in
   *         the main result of <code>criteria</code>
   */
  public Criterion isIn(final Field field, final Criteria<?> criteria)
  {
    return new MemoryIsInCriterion(((AbstractMemoryField) field), ((MemoryCriteria<?>) criteria));
  }



  /**
   * Return a criterion that represents that a field is contained in another
   * field (the second field must be a collection).
   * 
   * @param field1
   *          the field to search
   * @param field2
   *          the field to search in
   * @return a criterion representing that <code>field1</code> is contained in
   *         the field <code>field2</code>
   */
  public Criterion isIn(final Field field1, final Field field2)
  {
    return new MemoryIsInCriterion(((AbstractMemoryField) field1), ((AbstractMemoryField) field2));
  }



  /**
   * Return a criterion that represents that a field is <code>null</code>.
   * 
   * @param field
   *          the field to check
   * @return a criterion that represents that a field is <code>null</code>
   */
  public Criterion isNull(final Field field)
  {
    return new MemoryIsNullCriterion(((AbstractMemoryField) field));
  }



  /**
   * Return a criterion that represents that a field match another.
   * 
   * @param field1
   *          the first field in the matching
   * @param field2
   *          the second field in the matching
   * @param matchMode
   *          the type of match
   * @return a criterion representing that <code>field1</code> match
   *         <code>field2</code>
   */
  public Criterion like(final Field field1, final Field field2, final MatchMode matchMode)
  {
    return new MemoryFuzzyFieldComparator(((AbstractMemoryField) field1), ((AbstractMemoryField) field2), matchMode);
  }



  /**
   * Return a criterion that represents the negation of another criterion.
   * 
   * @param criterion
   *          the critertion to negate
   * @return a criterion representing the negation of <code>criterion</code>
   */

  public MemoryCriterion not(final Criterion criterion)
  {
    return new MemoryNotCriterion(((MemoryCriterion) criterion));
  }



  /**
   * Return a <code>Criterion</code> that always accept.
   * 
   * @return a <code>Criterion</code> that always deny
   * @see com.genia.toolbox.persistence.manager.RestrictionsManager#accept()
   */
  public Criterion accept()
  {
    return new MemoryAndJunction(getMemoryPersistenceManager());
  }

}
